#include "utils.hpp"
#include "Real.hpp"

/* 
 * Método de Ramanujan para calcular PI
 * ====================================
 * Cálculo:
 * 1 / PI = sqrt(8)/9801 * Sum_n=0^inf[ (4n)!*(1103+26390n) / ((n!)^4 * 396^(4n)) ]
 *
 */
template<typename T>
T ramanujan( Iteration iterations )
{

	T result  = 0.0f; // resultado
	T fact_4n = 1;    // (4n)!
	T fact_n  = 1;    // n!
	T pow_396 = 1;    // 396^4n

	// sumatoria desde 1 a la cantidad de iteraciones elegida
	for( Iteration n = 1 ; n < iterations ; n++ )
	{

		// recalcula los factoriales y 396^(4n) usando la iteración anterior
		unsigned long long y = 4*n;
		fact_4n *= static_cast<T>(y*(y-1)*(y-2)*(y-3));
		fact_n  *= static_cast<T>(n);
		pow_396 *= static_cast<T>(24591257856); // pow_396 *= 396^4

		// calcula el término n de la serie
		T term = static_cast<T>(fact_4n * static_cast<T>(1103+26390*n)) / static_cast<T>( pow(fact_n,4) * pow_396 );
		
		result += term;
	}

	result += 1103;
	result *= sqrt( 8 ) / 9801;

	return 1.0f/result;

}

int main(int argc, char** argv)
{

	return run( &ramanujan<Real>, 3, argc, argv );

}

